from Clouds import CloudsRECCo
import numpy as np

class AdaptRECCo(object):
	
	def __init__(self, dim, param):
		self.u         = 0
		self.dimension = dim
		self.Theta     = 0.0*np.array([range(dim)])
		self.d_dead    = param[0]
		self.sigma_L   = 0.000001
		self.alphaList = param[1]
		self.u_min     = param[2]
		self.u_max     = param[3]

	def fnAdaptiveLaw(self, inputList, memberList, statusEvolve, iK):
		lastTheta = self.Theta
		idxC      = np.argmax(memberList)
		[err, eps, iEps, dEps, r] = inputList
		
		#print(iK, "........", inputList)
		
		errAdaptList   = (np.array([err*eps, err*dEps, err*dEps, eps]))/(1+r*r)
		errControlList = np.array([eps, iEps, dEps, 1])
		
		if iK<500:
			errAdaptList[0:3] = abs(errAdaptList[0:3])
			
		if statusEvolve == True:
			if iK==1:
				self.Theta = lastTheta
			else:
				newTheta   = np.mean(lastTheta, axis=0)
				self.Theta = np.vstack([lastTheta, newTheta])
		else:
		# DEAD ZONE:
			if (abs(eps)<self.d_dead):
				self.Theta[idxC,:] = (1-self.sigma_L)*self.Theta[idxC,:]
			else:
				self.Theta[idxC,:] = (1-self.sigma_L)*self.Theta[idxC,:] + (self.alphaList*memberList[idxC])*errAdaptList
		
		# PARAMETER PROJECTION:
		self.Theta[idxC,self.Theta[idxC,:]<[0, 0, 0, -float("inf")]]=0

		# CALCULATE CONTROL SIGNAL:
		self.u = self.u_min + sum(((self.Theta).T*memberList).T).dot(errControlList.T)

		# INTERUPTION OF ADAPTATION
		if (self.u > self.u_max or self.u < self.u_min):
			if statusEvolve==False:
				self.Theta = lastTheta
			
			self.u = max(min(self.u, self.u_max), self.u_min)
